import OpenAI from 'openai';
import { spawn } from 'child_process';

// 使用硅基流动的API配置
const client = new OpenAI({
  apiKey: "<替换为你的API Key>",
  baseURL: "https://api.siliconflow.cn/v1"
});

class SimpleMCPClient {
  constructor() {
    this.serverProcess = null;
    this.tools = [];
    this.requestId = 0;
    this.pendingRequests = new Map();
  }

  async connectToServer(serverScriptPath) {
    /**
     * 连接到MCP服务器
     * @param {string} serverScriptPath - 服务器脚本路径
     */
    try {
      // 启动MCP服务器进程
      this.serverProcess = spawn(process.execPath, [serverScriptPath], {
        stdio: ['pipe', 'pipe', 'pipe'] 
      });

      // 设置数据接收处理
      this.serverProcess.stdout.on('data', (data) => {
        this.handleServerResponse(data.toString());
      });

      this.serverProcess.stderr.on('data', (data) => {
        console.error('Server error:', data.toString());
      });

      // 发送初始化请求
      await this.sendRequest({
        jsonrpc: "2.0",
        id: ++this.requestId,
        method: "initialize",
        params: {
          protocolVersion: "2024-11-05",
          capabilities: {},
          clientInfo: {
            name: "mcp-client-no-sdk",
            version: "1.0.0"
          }
        }
      });

      // 发送initialized通知
      this.sendNotification({
        jsonrpc: "2.0",
        method: "notifications/initialized"
      });

      // 获取工具列表
      const toolsResponse = await this.sendRequest({
        jsonrpc: "2.0",
        id: ++this.requestId,
        method: "tools/list"
      });

      this.tools = toolsResponse.result.tools.map((tool) => ({
        name: tool.name,
        description: tool.description,
        input_schema: tool.inputSchema,
      }));
      
      console.log(
        "已连接到MCP服务器，发现如下可用工具:",
        this.tools.map(({ name }) => name),
      );
    } catch (e) {
      console.log("Failed to connect to MCP server: ", e);
      throw e;
    }
  }

  handleServerResponse(data) {
    const lines = data.trim().split('\n');
    for (const line of lines) {
      if (line.trim()) {
        try {
          const response = JSON.parse(line);
          if (response.id && this.pendingRequests.has(response.id)) {
            const { resolve, reject } = this.pendingRequests.get(response.id);
            this.pendingRequests.delete(response.id);
            if (response.error) {
              reject(new Error(response.error.message));
            } else {
              resolve(response);
            }
          }
        } catch (e) {
          console.error('Failed to parse server response:', line, e);
        }
      }
    }
  }

  async sendRequest(request) {
    return new Promise((resolve, reject) => {
      this.pendingRequests.set(request.id, { resolve, reject });
      const requestStr = JSON.stringify(request) + '\n';
      this.serverProcess.stdin.write(requestStr);
      
      // 设置超时
      setTimeout(() => {
        if (this.pendingRequests.has(request.id)) {
          this.pendingRequests.delete(request.id);
          reject(new Error('Request timeout'));
        }
      }, 1000);
    });
  }

  sendNotification(notification) {
    const notificationStr = JSON.stringify(notification) + '\n';
    this.serverProcess.stdin.write(notificationStr);
  }

  async callTool(name, arguments_) {
    const response = await this.sendRequest({
      jsonrpc: "2.0",
      id: ++this.requestId,
      method: "tools/call",
      params: {
        name,
        arguments: arguments_
      }
    });
    return response.result;
  }

  // 请求大模型
  async fetchLLM(messages){
    return await client.chat.completions.create({
      model: "Qwen/Qwen3-8B",
      max_tokens: 1000,
      enable_thinking: false,
      messages,
      tools: this.tools.map(tool => ({
        type: 'function',
        function: {
          name: tool.name,
          description: tool.description,
          parameters: tool.input_schema
        }
      })),
    });
  }

  async processQuery(query) {
    /**
     * 使用OpenAI和可用工具处理问题
     * @param {string} query - 用户的输入问题
     * @returns {string} 处理后的响应
     */
    const messages = [
      {
        role: "user",
        content: query,
      },
    ];

    // 首次调用大模型，根据“用户的提问内容”结合“可用工具函数列表信息”进行【意图识别】并【给出工具函数调用决策】）
    const response = await this.fetchLLM(messages);
    // 处理响应和工具调用
    const message = response.choices[0].message;
    const finalText = [];
    const toolResults = [];

    // 如果有文本内容
    if (message.content) {
      finalText.push(message.content);
    }

    // 如果有工具调用
    if (message.tool_calls) {
      for (const toolCall of message.tool_calls) {
        const toolName = toolCall.function.name;
        const toolInput = JSON.parse(toolCall.function.arguments);
        
        console.log(`🔧 调用工具"${toolName}",传入${JSON.stringify(toolInput)}`);
        
        try {
          const result = await this.callTool(toolName, toolInput);
          
          const toolOutput = result.content[0]?.text || JSON.stringify(result.content);
          console.log(`🔧 获取结果:`, toolOutput);
          
          toolResults.push({
            tool_call_id: toolCall.id,
            role: "tool",
            content: toolOutput,
          });
        } catch (error) {
          console.error(`Tool execution failed:`, error);
          toolResults.push({
            tool_call_id: toolCall.id,
            role: "tool",
            content: `Error: ${error.message}`,
          });
        }
      }
    }

    // 如果有工具调用，需要再次调用API获取最终响应
    if (toolResults.length > 0) {
      messages.push({
        role: "assistant",
        content: message.content,
        tool_calls: message.tool_calls,
      });
      
      // 添加工具调用结果
      messages.push(...toolResults);

      const finalResponse = await this.fetchLLM(messages);
      
      // 再次调用大模型，整合【用户原始问题】、【函数调用决策】及【函数调用结果】给出最终结果。
      return finalResponse.choices[0].message.content || "";
    }

    return finalText.join("\n");
  }

  async disconnect() {
    if (this.serverProcess) {
      this.serverProcess.kill();
    }
  }
}

// 主程序
async function main() {
  const mcpClient = new SimpleMCPClient();
  
  try {
    // 连接到MCP服务器
    await mcpClient.connectToServer("./server/server-multi-tools.js");
    
    // 等待一下确保连接稳定
    await new Promise(resolve => setTimeout(resolve, 1000));
    
    // 测试问题
    const prompts = [
      "英文单词strawberry中有多少个r?"
    ];
    
    for (const prompt of prompts) {
      console.log(`\n🔍️ 问题: ${prompt}`);
      const result = await mcpClient.processQuery(prompt);
      console.log(`🎯 回答: ${result}\n\n`);
    }
  } catch (error) {
    console.error("Error:", error);
  } finally {
    await mcpClient.disconnect();
  }
}

// 运行主程序
main().catch(console.error);